package cn.wolfcode.shop.cloud.service.impl;
import cn.wolfcode.shop.cloud.common.BusinessException;
import cn.wolfcode.shop.cloud.common.Result;
import cn.wolfcode.shop.cloud.domain.Good;
import cn.wolfcode.shop.cloud.domain.SeckillGood;
import cn.wolfcode.shop.cloud.feign.GoodFeignApi;
import cn.wolfcode.shop.cloud.mapper.SeckillGoodMapper;
import cn.wolfcode.shop.cloud.service.ISeckillGoodService;
import cn.wolfcode.shop.cloud.service.RedisService;
import cn.wolfcode.shop.cloud.util.SeckillKeyPrefix;
import cn.wolfcode.shop.cloud.vo.SeckillGoodVO;
import cn.wolfcode.shop.cloud.msg.SeckillGoodCodeMsg;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class SeckillGoodServiceImpl implements ISeckillGoodService {
    //在内存中进行聚合操作
    @Autowired
    private SeckillGoodMapper seckillGoodMapper;
    @Autowired
    private GoodFeignApi goodFeignApi;
    @Autowired
    private RedisService redisService;

    public List<SeckillGoodVO> commom(List<SeckillGood> seckillGoods) {
        //拿到商品的id集合，放到set集合里：（去重复）
        Set<Long> GoodIds = new HashSet<>();
        for (SeckillGood seckillGood : seckillGoods) {
            GoodIds.add(seckillGood.getGoodId());
        }
        //2：根据id集合远程调用查询List<Good>集合
        Result<List<Good>> result = goodFeignApi.queryByGoodIds(GoodIds);
        if (result == null || result.getCode() != 200) {
            throw new BusinessException(SeckillGoodCodeMsg.REMOTE_GOOD_ERROR);
        }

        //3：在内存中进行聚合操作
        //new 一个map集合，暂时存放商品集合(key:商品id),来保证聚合到同一个vo对象里
        Map<Long, Good> map = new HashMap<>();
        for (Good good : result.getData()) {
            map.put(good.getId(), good);
        }
        List<SeckillGoodVO> vos = new ArrayList<>();
        for (SeckillGood seckillGood : seckillGoods) {
            SeckillGoodVO vo = new SeckillGoodVO();
            //从map能通过商品id取除商品对象，复制给vo对象
            Good good = map.get(seckillGood.getGoodId());
            BeanUtils.copyProperties(good, vo);
            BeanUtils.copyProperties(seckillGood, vo);
            vos.add(vo);
        }


        return vos;
    }


    @Override
    public SeckillGoodVO queryById(Long seckillId) {
        SeckillGood seckillGood = seckillGoodMapper.queryById(seckillId);
        List<SeckillGoodVO> vos = commom(Arrays.asList(seckillGood));
        return vos.get(0);
    }

    @Override
    public List<SeckillGoodVO> query() {
        //1：查询 List<SeckillGood>集合
        List<SeckillGood> seckillGoods = seckillGoodMapper.list();
        return commom(seckillGoods);
    }

    @Override
    //减库存
    public int decr(Long seckillId) {
        int count = seckillGoodMapper.decr(seckillId);
        return count;
    }

    @Override
    public SeckillGoodVO queryByIdByRedis(Long seckillId) {
        SeckillGoodVO seckillGoodVO = redisService.hGet(SeckillKeyPrefix.REDIS_SECKILL_VO, "", seckillId + "", SeckillGoodVO.class);
        //拿到预库存
        Integer count = redisService.get(SeckillKeyPrefix.SECKILL_STOCK_COUNT, seckillId + "", Integer.class);
        if (count<=0){
            count=0;
        }
        seckillGoodVO.setStockCount(count);
        return seckillGoodVO;
    }

    @Override
    public List<SeckillGoodVO> queryByRedis() {
        Map<String, SeckillGoodVO> voMap = redisService.hGetAll(SeckillKeyPrefix.REDIS_SECKILL_VO, "", SeckillGoodVO.class);
       //要的是他的value集合
        Collection<SeckillGoodVO> values = voMap.values();
        //转换为 ArrayList集合
        List<SeckillGoodVO> vos = new ArrayList<>(values);
        for (SeckillGoodVO vo : vos) {
            Integer count = redisService.get(SeckillKeyPrefix.SECKILL_STOCK_COUNT, vo.getId() + "", Integer.class);
            if (count<=0){
                count=0;
            }
            vo.setStockCount(count);
        }

        return vos;
    }

    @Override
    public void incrStockCount(Long goodId) {
        seckillGoodMapper.incrStockCount(goodId);

    }

    @Override
    public void incrRedisStockCount(Long goodId) {
        SeckillGoodVO seckillGoodVO = this.queryById(goodId);
        Integer stockCount = seckillGoodVO.getStockCount();
        redisService.set(SeckillKeyPrefix.SECKILL_STOCK_COUNT,goodId+"",stockCount);
    }
}
